-
Notifications
You must be signed in to change notification settings - Fork 365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved performance of adding rows and columns to the WTable #154
base: master
Are you sure you want to change the base?
Conversation
The issue was the calling of WTableRow::rowNum() for every added cell, which iterated over the whole table. The methods WTableRow::createCell() and WTableRow::insertColumn() got the new row argument defaulting to -1 that WTable can use when creating new elements with WTable::insertRow() and WTable::insertColumn(). These methods are called by WTable::expand() so the performance improvement affects every operation that expands the table. The performance of populating a new table row by row is increased with this commit from O(n^2+n) to O(n).
I'm not sure about this approach of smuggling the row number into the insertColumn() call, thereby changing the signature virtual method WTableRow::createCell(). I do wonder why that method is protected virtual yet not documented. Maybe it does not need to be. Also, it appears that WTable::createCell() does not use the row and column number by default, so it is a bit unfortunate that rowNum() gets called and then eventually the result is unused. I think it is best that the WTableRow contains its row number (meaning that any insertions or deletions of rows require an update of the row numbers), and perhaps similarly, WTableColumn contains its column number. Regards, |
This reverts commit 316f6b1.
Two of them (moveRow2 and moveColumn2) do not pass because of a bug in the WTable's code, which is not adressed in this commit. That's why these ones are disabled. The tests are not that comprehensive and were created to test the correctnes of code in future commits adressing WTable's performance.
- Added new field to WTableRow - rowNumber_ - to track its position in the table_. - Added WTable::updateRowNumbers() function to update row numbers for rows that need updating. - Modified WTable::insertRow(), WTable::removeRow() and WTable::moveRow() to update row numbers for the rows affected by these operations. - Modified WTableCell::rowNum() to use WTableCell::rowNumber_ if present. Adding rows at the end of the array is now much, much faster. It doesn't need to iterate over every cell anymore. Modified methods from WTable are a little slower than before when removing, inserting or moving rows from the middle of the array. This is because of added overhead of having to update row numbers but this slowdown is negligible.
I somehow missed The two tests in 989c2ad are disabled because of a bug they uncovered. I didn't want to fix it in this pull request but didn't want to remove the tests. When moving from the middle of the vector to its end an extra item is added after the inserted one, so the tests show that the vector is longer than it should be. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've got some more comments before this could actually be merged into Wt.
@@ -148,6 +148,7 @@ class WT_API WTableRow : public WObject | |||
std::string id_; | |||
WT_USTRING styleClass_; | |||
bool hidden_, hiddenChanged_, wasHidden_; | |||
size_t rowNumber_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be an int
for consistency.
@@ -0,0 +1,269 @@ | |||
/* | |||
* Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Copyright (C) 2010 Emweb bvba, Kessel-Lo, Belgium. | |
* Copyright (C) 2022 Emweb bv, Herent, Belgium. |
Wt::Test::WTestEnvironment environment; | ||
Wt::WApplication testApp(environment); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't create a WTestEnvironment
and WApplication
. Every test should create its own, so that tests are nicely isolated.
Wt::Test::WTestEnvironment environment; | ||
Wt::WApplication testApp(environment); | ||
|
||
void CheckRowNumbers(WTable* table) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void CheckRowNumbers(WTable* table) | |
void checkRowNumbers(WTable* table) |
Wt uses lowerCamelCase
for functions.
BOOST_REQUIRE_EQUAL(table->rowAt(i)->rowNum(), i); | ||
} | ||
} | ||
void CheckColumnNumbers(WTable* table) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
void CheckColumnNumbers(WTable* table) | |
void checkColumnNumbers(WTable* table) |
@@ -197,6 +197,7 @@ class WT_API WTable : public WInteractWidget | |||
void expand(int row, int column, int rowSpan, int columnSpan); | |||
WTableCell *itemAt(int row, int column); | |||
void setItemAt(int row, int column, std::unique_ptr<WTableCell> cell); | |||
void updateRowNumbers(int begin, int end); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
firstRow
and lastRow
is probably more clear than begin
and end
. It's also best that you throw in some documentation that clarifies that the lastRow
is inclusive.
|
||
BOOST_AUTO_TEST_CASE( elementAt1 ) | ||
{ | ||
auto table = cpp14::make_unique<WTable>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cpp14::make_unique
was deprecated: use std::unique
now instead.
@@ -451,6 +458,16 @@ void WTable::moveColumn(int from, int to) | |||
repaint(RepaintFlag::SizeAffected); | |||
} | |||
|
|||
void WTable::updateRowNumbers(int begin, int end) { | |||
if (begin < 0 || begin >= rowCount() || end < 0 || end >= rowCount()) { | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this ever happens that would be a programming error that's internal to Wt, right?
This should then either cause an alarming error message or should be omitted altogether.
return; | ||
} | ||
|
||
for (size_t i = begin; i <= end; ++i) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop uses size_t
, while begin
and end
are int
s?
rows_.insert(rows_.begin() + row, std::move(tableRow)); | ||
updateRowNumbers(std::min(old_end, row), rowCount() - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what situation would this not suffice?
updateRowNumbers(std::min(old_end, row), rowCount() - 1); | |
updateRowNumbers(row, rowCount() - 1); |
The issue was the calling of
WTableRow::rowNum()
for every added cell,which iterated over the whole table.
The methods
WTableRow::createCell()
,WTableRow::insertColumn()
andWTableRow::expand()
got the new row argument defaulting to -1 thatWTable
can use when creating new elements withWTable::insertRow()
andWTable::insertColumn()
. These methods are called byWTable::expand()
so the performance improvement affects every operation that expands
the table.
The performance of populating a new table row by row is increased
with this commit from O(n^2+n) to O(n).